package com.moyuwanjia.service.impl;


import com.moyuwanjia.dao.UserDao;
import com.moyuwanjia.pojo.User;
import com.moyuwanjia.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author 摸鱼丸加~
 * @create 2022-04-19 11:18
 * @describe <P></P>
 * 我们都知道，对象实例化时（创建对象时），构造函数就会被调用，所以，验证对象
 * 是否被立即创建的方式，就是查看构造器有没有被调用
 * 曾经使用xml的方式注入
 *  <bean id="xxx"
 *          class="全限定类名" scope="" init-method="" destroy-method="">
 * 注解的分类:
 *     1.用于创建对象的 => 与<bean></bean>标签实现的功能一致
 *          @Component :用于把当前类存入spring容器中
 *          属性：value：指定bean的id，当不写时，默认值为当前类名（且首字母小写）
 *          以下三个注解的属性、作用都与Component是一样的，只不过是spring框架为我们提供明确的三层使用的注解
 *                  使得在开发过程中对象更加清晰
 *                  @Controller
 *                  @Service
 *                  @Repository
 *     2.用于注入数据的 => 与bean中的<property>标签的作用是一样的
 *          他们的作用就和在xml配置文件中的bean标签中写一个<property>标签的作用是一样的
 *          2.1.自动注入
 *          @Autowired:
 *              作用:自动按照类型注入。
 *               2.1如果容器中有唯一的一个[bean对象类型]和要注入的[变量类型匹配]，
 *              就可以注入成功
 *              2.2如果ioc容器中没有任何bean的类型和要注入的变量类型匹配，则报错
 *              2.3如果bean的类型与变量类型存在多个匹配，就会找不到指定的bean，也会报错
 *          该注解可以用在类、方法、参数、属性上等等
 *          细节：使用注解方式注入时，set方法就不是必须的了。
 *          2.2.修饰符
 *          @Qualifier:
 *              （不能单独使用，只能配合Autowired来使用）
 *              作用：按照类型注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法注入参数时可以
 *              属性：
 *                  value：用于指定注入的bean的id
 *
 *          2.3.Resource:
 *              作用：直接按照bean的id注入。它可以独立使用,使用name去指定bean的id，而不是像Autowired需要通过变量名去指定（会显得很不灵活），
 *              属性：
 *                  name：用于指定bean的id
 *         注意：以上三个注解只能用于bean类型的数据，基本数据类型和String类型无法使用上述注解实现注入
 *              而如果是集合类型，只能通过XML的方式来实现。
 *          Value:
 *              作用：用于注入基本类型和String类型的数据
 *              属性：
 *                  value：用于指定数据的值，也可以使用Spring中SpEL(spring中的el表达式)
 *                  SpEL的写法：${表达式}
 *     3.用于改变作用范围的 => 与bean标签中使用scope属性实现的功能是一样的
 *          Scope
 *              作用：
 *                  用于指定bean的作用范围
 *              属性：
 *                  value：指定范围的取值，这里只演示两个：singleton(单例)   prototype(多例)
 *
 *     4.用于和生命相关的 => 他们的作用就是和在bean标签中使用init-method和destroy-methods一致
 *         PreDestroy
 *              作用：用于指定销毁方法(注意：如果此时是多例，销毁是spring不负责的，所以多例对象不会起作用)
 *         PostConstruct
 *              作用：用于指定初始化方法
 *
 */
//@Component("userServiceImpl")
@Service("userServiceImpl")
@Scope(value = "prototype")
public class UserServiceImpl implements UserService {
    /**
     * 方式一：只能在IOC容器中只存在唯一一个Bean与注入的变量类型匹配的情况下使用
     * 当IOC中已注册的Bean的类型与需要注入的变量的类型存在多个匹配时，
     * 就会发生报错
     */
//    @Autowired
//    private UserDao userDao;

    /**
     * 方式二：在IOC容器中只存在一个或者多个Bean与变量类型匹配都可以使用，还需要使用限定符，较为繁琐，
     * 当IOC中已注册的Bean的类型与需要注入的变量的类型存在多个匹配时
     * 解决：使用Qualifier添加限定符，按照类型注入的基础上，再按照名称注入
     * （注意：不能单独使用，只能配合Autowired来使用）
     */
//    @Autowired
//    @Qualifier("userDao01")
//    private UserDao userDao;
    /**
     * 方式三：直接使用该注解的name属性指定Bean的id(也就是注册到IOC容器中的名称)
     */
//    @Resource(name = "userDao01")
//    private UserDao userDao;

    private final UserDao userDao;
    public UserServiceImpl(@Qualifier("userDao02") UserDao userDao) {
        this.userDao = userDao;
    }



    public User saveUsers(User user) {
        return userDao.insert(user);
    }

    @PostConstruct
    public void init01(){
        System.out.println("执行初始化。。。");
    }

    @PreDestroy
    public void destroy02(){
        System.out.println("执行销毁方法。。。");
    }
}
